package com.spzx.cart.service.Impl;

import com.spzx.cart.api.domain.CartInfo;
import com.spzx.cart.service.ICartService;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.context.SecurityContextHolder;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.api.domain.ProductSku;
import com.spzx.product.api.domain.SkuPrice;
import com.spzx.user.api.domain.UserInfo;
import jodd.util.CollectionUtil;
import nonapi.io.github.classgraph.utils.LogNode;
import org.redisson.api.RList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.w3c.dom.ls.LSInput;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * ClassName: CartServiceImpl
 * Package: com.spzx.cart.service.Impl
 * Description:
 *
 * @Author ycy
 * @Create 2024/8/21 11:32
 * @Version 1.0
 */
@Service
public class CartServiceImpl implements ICartService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RemoteProductService remoteProductService;
    @Override
    public void allCheckCart(Integer isChecked) {
        // 获取当前登录用户的id
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartInfoList = hashOperations.values();
        cartInfoList.forEach(item -> {
            CartInfo cartInfoUpd = hashOperations.get(item.getSkuId().toString());
            cartInfoUpd.setIsChecked(isChecked);

            // 更新缓存
            hashOperations.put(item.getSkuId().toString(), cartInfoUpd);
        });
    }

    private String getCartKey(Long userId) {
        //定义key user:userId:cart
        return "user:cart:" + userId;
    }


    @Override
    public void addToCart(Long skuId, Integer skuNum) {
        // 获取当前登录用户id
        Long userId = SecurityContextHolder.getUserId();
        // 1.构建”用户“购物车hash结构key user:用户ID:cart
        String cartKey = getCartKey(userId);
        // 2.创建Hash结构绑定操作对象（方便对hash进行操作）
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);

        // 4.判断用户购物车中是否包含该商品，如果包含：数量进行累加（某件商品数量上限99） 不包含：则新增购物车商品
        String hashKey = skuId.toString();
        Integer threshold = 99;
        if (hashOps.hasKey(hashKey)) {
            // 4.1 说明该商品已存在购物车，对数量进行累加，不能超过指定数量上限
            CartInfo cartInfo = hashOps.get(hashKey);
            int totalCount = cartInfo.getSkuNum() + skuNum;
            cartInfo.setSkuNum(totalCount > threshold ? threshold : totalCount);
            hashOps.put(hashKey, cartInfo);
        } else {
            // 3.判断购物车商品种类（不同SKU）总数大于50件
            Long count = hashOps.size();
            if (++count > 50) {
                throw new RuntimeException("商品种类数量超过上限");
            }
            // 4.说明购物车里没有商品，构建购物车对象，存入Redis
            CartInfo cartInfo = new CartInfo();
            cartInfo.setUserId(userId);
            cartInfo.setSkuNum(skuNum > threshold ? threshold : skuNum);
            cartInfo.setUpdateTime(new Date());
            cartInfo.setCreateTime(new Date());

            // 4.1 远程调用商品服务获取商品sku基本信息
            R<ProductSku> productSkuR = remoteProductService.getProductSku(skuId, SecurityConstants.INNER);
            if (R.FAIL == productSkuR.getCode()) {
                throw new ServiceException(productSkuR.getMsg());
            }
            ProductSku productSku = productSkuR.getData();
            cartInfo.setSkuId(skuId);
            cartInfo.setSkuName(productSku.getSkuName());

            cartInfo.setThumbImg(productSku.getThumbImg());

            // 4.2 远程调用商品服务获得商品实时价格
            R<SkuPrice> skuPriceR = remoteProductService.getSkuPrice(skuId, SecurityConstants.INNER);
            if (R.FAIL == productSkuR.getCode()) {
                throw new ServiceException(skuPriceR.getMsg());
            }
            SkuPrice skuPrice = skuPriceR.getData();
            cartInfo.setCartPrice(skuPrice.getSalePrice());

            // 4.3 将购物车商品存入Redis
            hashOps.put(hashKey, cartInfo);
        }
    }

    @Override
    public List<CartInfo> getCartList() {
        // 获取当前登录的用户userId
        Long userId = SecurityContextHolder.getUserId();
        //这里指代 CartService 实例
        String cartKey = this.getCartKey(userId);
        // 从缓存中根据 键 cartKey 获取cartInfoList
        List<CartInfo> cartInfoList = redisTemplate.opsForHash().values(cartKey);

        //购物车不为空的情况，按创建时间顺序排列购物车内商品，并更新实时价格
        if (!CollectionUtils.isEmpty(cartInfoList)) {
            // sorted 排序方法
            // Stream中的元素将按照createTime从大到小的顺序进行排序。
            List<CartInfo> infoList = cartInfoList.stream().sorted((o1, o2) ->
                    o2.getCreateTime().compareTo(o1.getCreateTime())).collect(Collectors.toList());

            // 获取skuId列表 （因为需要通过 skuId 获取商品实时价格列表）
            List<Long> skuIdList = infoList.stream().map(CartInfo::getSkuId).collect(Collectors.toList());

            //查询商品的实时价格
            R<List<SkuPrice>> SkuPriceListResult = remoteProductService.getSkuPriceList(skuIdList, SecurityConstants.INNER);
            if (R.FAIL == SkuPriceListResult.getCode()) {
                throw new ServiceException(SkuPriceListResult.getMsg());
            }
            // 创建 skuId 和 skuPrice 的键值对集合
            Map<Long, BigDecimal> skuIdToPriceMap = SkuPriceListResult.getData()
                    .stream()
                    .collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));
            // 遍历 infoList 设置其中每个 cartInfo 的 SkuPrice 为集合 skuIdToPriceMap 中对应 skuId 的价格
            infoList.forEach(item -> {
                item.setSkuPrice(skuIdToPriceMap.get(item.getSkuId()));
            });

            return infoList;
        }
        return new ArrayList<>();
    }

    @Override
    public void deleteCart(Long skuId) {
        //获取当前登录用户id
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        //获取缓存对象
        BoundHashOperations<String,String,CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);
        hashOperations.delete(skuId.toString());
    }

    @Override
    public void checkCart(Long skuId, Integer isChecked) {
        //获取当前用户id
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);

        //获取缓存对象
        BoundHashOperations<String,String,CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);

        // 获取用户选中商品
        if (hashOperations.hasKey(skuId.toString())){
            CartInfo cartInfoUpd = hashOperations.get(skuId.toString());
            // cartInfoUpd 写入缓存
            cartInfoUpd.setIsChecked(isChecked);
            // 更新缓存
            hashOperations.put(skuId.toString(),cartInfoUpd);
        }
    }

    @Override
    public void clearCart() {
        // 获取当前登录用户id
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        redisTemplate.delete(cartKey);
    }

    @Override
    public List<CartInfo> getCartCheckedList(Long userId) {
        List<CartInfo> cartInfoList = new ArrayList<>();

        String cartKey = this.getCartKey(userId);
        List<CartInfo> cartCachInfoList = redisTemplate.opsForHash().values(cartKey);
        if (!CollectionUtils.isEmpty(cartCachInfoList)){
            for (CartInfo cartInfo : cartCachInfoList) {
                if (cartInfo.getIsChecked().intValue() == 1){
                    cartInfoList.add(cartInfo);
                }
            }
        }
       return cartInfoList;
    }

    @Override
    public Boolean updateCartPrice(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> hashOperations =redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartCachInfoList = hashOperations.values();
        if (!CollectionUtils.isEmpty(cartCachInfoList)){
            for (CartInfo cartInfo : cartCachInfoList) {
                if (cartInfo.getIsChecked().intValue() == 1){
                    SkuPrice skuPrice = remoteProductService.getSkuPrice(cartInfo.getSkuId(), SecurityConstants.INNER).getData();
                    cartInfo.setCartPrice(skuPrice.getSalePrice());
                    cartInfo.setSkuPrice(skuPrice.getSalePrice());
                    hashOperations.put(cartInfo.getSkuId().toString(),cartInfo);
                }
            }
        }
        return true;
    }

    @Override
    public Boolean deleteCartCheckedList(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);
        List<CartInfo> cartCachInfoList = hashOperations.values();
        if (!CollectionUtils.isEmpty(cartCachInfoList)){
            for (CartInfo cartInfo : cartCachInfoList) {
                // 获取选中的商品
                if (cartInfo.getIsChecked().intValue() == 1){
                    hashOperations.delete(cartInfo.getSkuId().toString());
                }
            }
        }
        return true;
    }
}
